import { HubConnectionBuilder } from "@microsoft/signalr";

class SignalRClient {
    constructor() {
    }

    #map = new Map();

    /**
     * 初始化 SignalR 连接
     * @param {string} hubUrl - SignalR Hub URL
     * @param {object} [header=null] 自定义增加请求头
     * @param {String} [rndstr=''] 连接key随机，默认为空
     */
    init(hubUrl, header = null, rndstr = '') {
        let key = `srk_${hubUrl}${rndstr}`;
        if (this.#map.has(key)) {
            return key;
        }

        let conn = new HubConnectionBuilder()
            .withUrl(hubUrl, { headers: header})
            .build();
        if (!this.#map.has(key)) {
            this.#map.set(key, { id: key, connection:conn, listeners: {}, failConnect: true, flag: true });
        }

        conn.onclose(() => {
            console.log('SignalR connection closed, attempting to reconnect...');
            if (this.#map.get(key).flag) {
                setTimeout(() => this.start(this.#map.get(key).id, this.#map.get(key).failConnect), 5000); // 自动重连
            }
        });

        return key;
    }

    /**
     * 启动 SignalR 连接
     * @param {string} initKey - init function return value
     */
    async start(initKey, isAutoReconnect = false) {
        if (!this.#map.has(initKey)) {
           throw new Error("Please first execute the init method to get the initkey");
        }
        let obj = this.#map.get(initKey);
        try {
            obj.failConnect = isAutoReconnect;
            if (obj.connection.state === 'Disconnected') {
                await obj.connection.start();
                console.log('SignalR connected successfully.');
            }
            obj.flag = true;
        } catch (error) {
            console.error('SignalR Error while starting SignalR connection:', error);
            if (isAutoReconnect) {
                setTimeout(() => this.start(obj.id, obj.failConnect), 5000); // 自动重连
            }
        }
    }

    /**
     * 添加事件监听器
     * @param {string} initKey - init function return value
     * @param {string} eventName - 事件名称
     * @param {Function} callback - 回调函数
     */
    on(initKey, eventName, callback) {
        if (!this.#map.has(initKey)) {
           throw new Error("Please first execute the init method to get the initkey");
        }
        let obj = this.#map.get(initKey);
        if (!obj.listeners[eventName]) {
            obj.listeners[eventName] = [];
            // 注册 SignalR 事件监听器
            obj.connection.on(eventName, (...args) => {
                obj.listeners[eventName].forEach(listener => listener(...args));
            });
        }

        if (!obj.listeners[eventName].some(el => el === callback)) {
            obj.listeners[eventName].push(callback);
        }
    }

    /**
     * 移除事件监听器
     * @param {string} initKey - init function return value
     * @param {string} eventName - 事件名称
     * @param {Function} callback - 要移除的回调函数
     */
    off(initKey, eventName, callback) {
        if (!this.#map.has(initKey)) {
           throw new Error("Please first execute the init method to get the initkey");
        }
        let obj = this.#map.get(initKey);
        if (obj.listeners[eventName]) {
            obj.listeners[eventName] = obj.listeners[eventName].filter(listener => listener !== callback);
        }
    }

    /**
     * 移除事件监听器
     * @param {string} initKey - init function return value
     * @param {string} eventName - 事件名称
     */
    off(initKey, eventName) {
        if (!this.#map.has(initKey)) {
           throw new Error("Please first execute the init method to get the initkey");
        }
        let obj = this.#map.get(initKey);
        if (obj.listeners[eventName]) {
            obj.listeners[eventName] = [];
        }
    }

    /**
     * 发送消息到服务器
     * @param {string} initKey - init function return value
     * @param {string} methodName - 方法名称
     * @param {...any} args - 参数
     */
    async invoke(initKey, methodName, ...args) {
        if (!this.#map.has(initKey)) {
           throw new Error("Please first execute the init method to get the initkey");
        }
        let obj = this.#map.get(initKey);
        if (obj.connection && obj.connection.state === 'Connected') {
            try {
                await obj.connection.invoke(methodName, ...args);
            } catch (error) {
                console.error(`SignalR Error invoking method "${methodName}":`, error);
            }
        } else {
            console.warn('SignalR is not connected.');
        }
    }

    /**
     * 关闭 SignalR 连接
     * @param {string} initKey - init function return value
     */
    stop(initKey) {
        if (!this.#map.has(initKey)) {
            return;
        }
        let obj = this.#map.get(initKey);
        obj.flag = false;
        if (obj.connection) {
            obj.connection.stop();
            console.log('SignalR connection stopped.');
        }
    }

    /**
     * 释放组件,必须重新监听处理程序和打开连接
     * @param {string} initKey - init function return value
     */
    dispose(initKey) {
        if (!this.#map.has(initKey)) {
            return;
        }
        this.stop(initKey);
        let obj = this.#map.get(initKey);
        obj.listeners = {};
        this.#map.delete(initKey);
    }
}

// 导出单例实例
export const SClient = new SignalRClient();